#include<stdio.h>  
#include<stdlib.h>  
#include<ctype.h>  
#include<string.h>  
#include<unistd.h>  
#include<fcntl.h>  
#include<sys/types.h>  
#include<sys/wait.h>  
#include<dirent.h>  
  
char mingling[100]; 
char argv[50][50];
int cou;         
enum specify{NORMAL,OUT_REDIRECT,IN_REDIRECT,PIPE};  
  

int analysis_mingling();  
int do_mingling();  
int find_mingling(char *mingling);   
int main()  
{  
    while(1){  
        printf("$");  
    mingling[0]=0;  
        gets(mingling);  
        if(!analysis_mingling())  
       continue;   
    do_mingling();  
    }  
    return 0;  
}  
  
int analysis_mingling()  
{  
    char *s=mingling;  
    int i=0,j=0,state=0;  
    strcat(mingling," ");  
       while(*s){  
    switch(state){  
           case 0:  
           if(!isspace(*s))  
           state=1;  
           else  
           s++;  
           break;  
       case 1:  
           if(isspace(*s)){  
           argv[i][j]='\0';  
           i++;  
           j=0;  
           state=0;  
           }else{  
           argv[i][j]=*s;  
           j++;  
           }  
           s++;  
           break;  
    }  
    }  
    cou=i;  
    if(cou==0)  
    return 0;  
  
    if(strcmp(argv[0],"logout")==0 || strcmp(argv[0],"exit")==0)  
    exit(0);  
  
  
    if(!find_mingling(argv[0])){  
    puts("error:can't find mingling");  
    return 0;  
    }  
    return 1;     
}  
  
int do_mingling()  
{  
    int i,j;  
    char* file;  
    char* argv[50];  
    char* argv2[50];  
    int f=0,back_run=0;  
    int fd,pid,fd2,pid2;  
    enum specify type=NORMAL;  
  
    for(i=0;i<cou;i++){  
    argv[i]=argv[i];  
    }  
    argv[i]=NULL;  
  
    if(strcmp(argv[cou-1],"<")==0 || strcmp(argv[cou-1],">")==0 || strcmp(argv[cou-1],"|")==0){  
    printf("error:mingling error\n");  
    return 0;  
    }  
          
    for(i=0;i<cou;i++){  
    if(strcmp(argv[i],"<")==0){  
            f++;  
        file=argv[i+1];  
        argv[i]=NULL;  
        type=IN_REDIRECT;  
    }else if(strcmp(argv[i],">")==0){  
        f++;  
        file=argv[i+1];  
        argv[i]=NULL;  
        type=OUT_REDIRECT;  
    }else if(strcmp(argv[i],"|")==0){  
        f++;  
        type=PIPE;  
        argv[i]=NULL;  
        for(j=i+1;j<cou;j++){  
        argv2[j-i-1]=argv[j];  
        }  
        argv2[j-i-1]=NULL;  
        if(!find_mingling(argv2[0])){  
        printf("error:can't find mingling\n");  
        return 0;  
        }  
    }  
    }  
  
    if(strcmp(argv[cou-1],"&")==0){  
    back_run=1;  
    argv[cou-1]=NULL;  
    }  
  
    if(f>1){  
    printf("error:don't identify the mingling");  
    return 0;  
    }  
  
    pid=fork();  
    if(pid<0){  
    perror("fork error");  
        exit(0);  
    }else if(pid==0){
        switch(type){  
            case NORMAL:  
        execvp(argv[0],argv);  
            break;  
        case IN_REDIRECT:  
        fd=open(file,O_RDONLY);  
        dup2(fd,STDIN_FILENO);  
                execvp(argv[0],argv);  
        break;  
        case OUT_REDIRECT:  
        fd=open(file,O_WRONLY|O_CREAT|O_TRUNC,0666);  
        dup2(fd,STDOUT_FILENO);  
        execvp(argv[0],argv);  
        break;  
        case PIPE:  
        pid2=fork();  
        if(pid2==0){  
            fd2=open("tempfile",O_WRONLY|O_CREAT|O_TRUNC,0600);  
            dup2(fd2,STDOUT_FILENO);  
            execvp(argv[0],argv);  
        }else{  
            waitpid(pid2,NULL,0);  
            fd=open("tempfile",O_RDONLY);  
            dup2(fd,STDIN_FILENO);  
            execvp(argv2[0],argv2);  
        }  
        break;  
        }  
    }else{  
       if(!back_run)  
           waitpid(pid,NULL,0);  
    }  
    return 1;  
}  
  
  
  
int find_mingling(char *mingling)  
{  
    DIR *d;  
    struct dirent *ptr;  
    char temp[100];  
    char *dir;  
    char *path=getenv("PATH");  
       strcpy(temp,path);  
    dir=strtok(temp,":");  
    while(dir){  
        d=opendir(dir);  
        while((ptr=readdir(d)) != NULL)  
        if(strcmp(ptr->d_name,mingling) == 0){  
        closedir(d);  
        return 1;  
        }  
    closedir(d);  
    dir=strtok(NULL,":");  
    }  
    return 0;  
}  

